package com.rr.learningdemo.instalnce;

/**
 * @author RR
 * @date 2021/3/12 15:18
 */

//双重检查锁单例模式
public class DoubleCheckInstance {
    /*
    * volatile用来保证多线程情况下new instance时指令的原子性
    * 因为它可能在new的时候对指令进行重排序
    * new的三个步骤：（1）创建对象、（2）初始化对象、（3）分配对象引用
    * 可能会被指令重排为（1）（3）（2）
    * 若被重排则可能别的线程拿到了该对象的引用，但它却还没初始化，从而出现问题
    * volatile正是保证多线程状态下，这初始化的三个步骤能一起执行
    * */
    private static volatile DoubleCheckInstance instance = null;

    public static DoubleCheckInstance getInstance() {
        //如果判断不为null了，直接获取对象，因为加锁存在不小的开销，因此先做检查
        if (instance == null) {
            //可能同时存在多个线程一起进到这里，下面进行加锁
            synchronized (DoubleCheckInstance.class) {
                //因为可能有多个线程在这里等等获得锁并进入下面方法，因此需要再进行一次判断
                if (instance == null) {
                    instance = new DoubleCheckInstance();
                }
            }
        }
        return instance;
    }
}
